#include "cst816d.h"
#include "driver/gpio.h"
#include "driver/i2c.h"
#include "driver/spi_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "st7789.h"
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "lv_demos.h"
#include "lv_port_disp_template.h"
#include "lv_port_indev_template.h"
#include "lvgl.h"

extern struct st7789 lcd;
extern struct cst816d tp;
extern bool flag;

#define LVGL_TICK 10

typedef struct point {
	int x;
	int y;
} point_t;

typedef struct rect {
	int x;
	int y;
	int w;
	int h;
} rect_t;

#define ST7789_CLK_PIN  2
#define ST7789_MOSI_PIN 3
#define ST7789_CS_PIN   10
#define ST7789_RST_PIN  6
#define ST7789_DC_PIN   7
#define ST7789_BL_PIN   11

/* 矩形框 */
static int g_fill_flag[3][3] = { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } };
static rect_t g_rect[3][3] = {
	[0] = {
	    [0] = {
	        .x = 20,
	        .y = 20,
	        .w = 40,
	        .h = 40,
	    },
	    [1] = {
	        .x = 100,
	        .y = 20,
	        .w = 40,
	        .h = 40,
	    },
	    [2] = {
	        .x = 180,
	        .y = 20,
	        .w = 40,
	        .h = 40,
	    },
	},
	[1] = {
	    [0] = {
	        .x = 20,
	        .y = 120,
	        .w = 40,
	        .h = 40,
	    },
	    [1] = {
	        .x = 100,
	        .y = 120,
	        .w = 40,
	        .h = 40,
	    },
	    [2] = {
	        .x = 180,
	        .y = 120,
	        .w = 40,
	        .h = 40,
	    },
	},
	[2] = {
	    [0] = {
	        .x = 20,
	        .y = 220,
	        .w = 40,
	        .h = 40,
	    },
	    [1] = {
	        .x = 100,
	        .y = 220,
	        .w = 40,
	        .h = 40,
	    },
	    [2] = {
	        .x = 180,
	        .y = 220,
	        .w = 40,
	        .h = 40,
	    },
	},
};

void lcd_draw_rect(rect_t* rect, uint16_t color)
{
	point_t p_up_left;
	point_t p_up_rigth;
	point_t p_down_left;
	point_t p_down_rigth;

	p_up_left.x = rect->x;
	p_up_left.y = rect->y;

	p_up_rigth.x = rect->x + rect->w - 1;
	p_up_rigth.y = rect->y;

	p_down_left.x = rect->x;
	p_down_left.y = rect->y + rect->h - 1;

	p_down_rigth.x = rect->x + rect->w - 1;
	p_down_rigth.y = rect->y + rect->h - 1;

	// 矩形上面的横线
	st7789_rect_fill_color(&lcd, p_up_left.x, p_up_left.y, p_up_rigth.x, p_up_rigth.y, color);

	// 矩形下面的横线
	st7789_rect_fill_color(&lcd, p_down_left.x, p_down_left.y, p_down_rigth.x, p_down_rigth.y, color);

	// 矩形左边的竖线
	st7789_rect_fill_color(&lcd, p_up_left.x, p_up_left.y, p_down_left.x, p_down_left.y, color);

	// 矩形右边的竖线
	st7789_rect_fill_color(&lcd, p_up_rigth.x, p_up_rigth.y, p_down_rigth.x, p_down_rigth.y, color);
}

void app_main(void)
{
	int i = 0;
	int j = 0;
	int sum = 0;

	lv_init();
	printf("success: lv_init()\n");

	lv_port_disp_init();
	printf("success: lv_port_disp_init()\n");

	lv_port_indev_init();
	printf("success: lv_port_indev_init()\n");

	int ret = 0;
	bool pressed = 0;
	uint16_t x = 0;
	uint16_t y = 0;
	int dot = 1;

	/* white background */
	st7789_rect_fill_color(&lcd, 0, 0, lcd.cfg.fix.width - 1, lcd.cfg.fix.height - 1, RGB565_WHITE);

	for (i = 0; i < 3; i++) {
		for (j = 0; j < 3; j++) {
			lcd_draw_rect(&g_rect[i][j], RGB565_BLACK);
		}
	}

	while (1) {
		if (flag) {
			/* get coord */
			ret = cst816d_get_coord(&tp, &pressed, &x, &y);
			if (0 == ret) {
				rect_t* r = NULL;
				/* read coord successful, then lcd dram point */
				printf("tp: (%d, %d)\n", x, y);
				st7789_rect_fill_color(&lcd, x, y, x + dot, y + dot, RGB565_RED);

				sum = 0;
				for (i = 0; i < 3; i++) {
					for (j = 0; j < 3; j++) {
						r = &g_rect[i][j];

						if ((x > r->x) && (x < r->x + r->w) && (y > r->y) && (y < r->y + r->h) && (0 == g_fill_flag[i][j])) {
							g_fill_flag[i][j] = 1;
							printf("fill: i = %d, j = %d\n", i, j);
							st7789_rect_fill_color(&lcd, r->x, r->y, r->x + r->w - 1, r->y + r->h - 1, RGB565_RED);
							st7789_rect_fill_color(&lcd, x, y, x + dot, y + dot, RGB565_BLACK);
						} else {
							st7789_rect_fill_color(&lcd, x, y, x + dot, y + dot, RGB565_BLACK);
						}

						sum = sum + g_fill_flag[i][j];
					}
				}

				printf("sum = %d\n", sum);
				if (9 == sum) {
					printf("touch test successful\n");
					break;
				}
			}
			flag = 0;
		} else {
			vTaskDelay(10 / portTICK_PERIOD_MS);
		}
	}

	for (i = 0; i < 3; i++) {
		vTaskDelay(500 / portTICK_PERIOD_MS);
		lcd.ops.backlight(0);
		vTaskDelay(500 / portTICK_PERIOD_MS);
		lcd.ops.backlight(1);
	}

	lv_demo_widgets();

	while (1) {
		lv_tick_inc(LVGL_TICK);
		lv_timer_handler();
		usleep(LVGL_TICK * 1000);
	}
}
